package cc.rengu.redp.bizimpl.upmp.service.impl;

import cc.rengu.redp.bizimpl.constant.UpmpConstant;
import cc.rengu.redp.bizimpl.enums.ChannelTypeEnum;
import cc.rengu.redp.bizimpl.enums.IgasYesOrNoEnum;
import cc.rengu.redp.bizimpl.manager.UpmpUserManager;
import cc.rengu.redp.bizimpl.upmp.dao.UpmpRoleMenuMapper;
import cc.rengu.redp.bizimpl.upmp.domain.UpmpMenu;
import cc.rengu.redp.bizimpl.upmp.domain.UpmpRole;
import cc.rengu.redp.bizimpl.upmp.dao.UpmpRoleMapper;
import cc.rengu.redp.bizimpl.upmp.domain.UpmpRoleMenu;
import cc.rengu.redp.bizimpl.upmp.domain.UpmpSysParam;
import cc.rengu.redp.bizimpl.upmp.service.*;
import cc.rengu.redp.bizimpl.upmp.vo.UpmpRoleVO;
import cc.rengu.redp.bizimpl.upmp.vo.UpmpUserInfoVO;
import cc.rengu.redp.bizimpl.utils.CommonUtils;
import cc.rengu.redp.bizimpl.utils.RedpUpmpUtil;
import cc.rengu.redp.common.domain.QueryRequest;
import cc.rengu.redp.common.utils.DateUtil;
import cc.rengu.redp.common.utils.SortUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * @author System
 */
@Service("upmpRoleService")
@DS("upmp")
public class UpmpRoleServiceImpl extends ServiceImpl<UpmpRoleMapper, UpmpRole> implements IUpmpRoleService {

    @Autowired
    private IUpmpSysParamService upmpSysParamService;
    @Autowired
    private IUpmpMenuService upmpMenuService;
    @Autowired
    private IUpmpUserRoleService upmpUserRoleService;
    @Autowired
    private IUpmpRoleMenuService upmpRoleMenuService;
    @Autowired
    private UpmpRoleMenuMapper upmpRoleMenuMapper;
    @Autowired
    private UpmpUserManager upmpUserManager;


    @Override
    public IPage<UpmpRole> findRoles(UpmpRoleVO role, QueryRequest request) {
        try {
            LambdaQueryWrapper<UpmpRole> queryWrapper = new LambdaQueryWrapper<>();

            if (!StringUtils.isEmpty(role.getInstId())) {
                queryWrapper.eq(UpmpRole::getInstId, role.getInstId());
            }
            if (!StringUtils.isEmpty(role.getRoleName())) {
                queryWrapper.like(UpmpRole::getRoleName, role.getRoleName());
            }
            if (!StringUtils.isEmpty(role.getCreateTimeFrom()) && !StringUtils.isEmpty(role.getCreateTimeTo())) {
                queryWrapper
                        .ge(UpmpRole::getCreateTime, role.getCreateTimeFrom())
                        .le(UpmpRole::getCreateTime, role.getCreateTimeTo());
            }
            Page<UpmpRole> page = new Page<>();
            SortUtil.handlePageSort(request, page, true);
            return this.page(page, queryWrapper);
        } catch (Exception e) {
            log.error("获取角色信息失败", e);
            return null;
        }
    }

    @Override
    public List<UpmpRole> findUserRole(String userId) {
        return baseMapper.findUserRole(userId);
    }

    @Override
    public List<UpmpRole> findByName(String instId, String roleName) {
        return baseMapper.selectList(new LambdaQueryWrapper<UpmpRole>().and(lqw -> lqw.eq(UpmpRole::getInstId, instId)
                .eq(UpmpRole::getRoleName, roleName))
        );
    }

    @Override
    public UpmpRole findById(String id) {
        return baseMapper.selectById(id);
    }

    @Override
    public void createRole(UpmpRoleVO role) {
        UpmpRole newRole = new UpmpRole();
        BeanUtils.copyProperties(role, newRole);
        UpmpUserInfoVO user = CommonUtils.getCurrentUser(upmpSysParamService);
        newRole.setOprId(user.getId());
        newRole.setCreateTime(DateUtil.getDateFormat(new Date(), DateUtil.FULL_TIME_WITH_MILL_SPLIT_PATTERN));
        newRole.setRoleName(role.getRoleName().trim());
        newRole.setStatus(IgasYesOrNoEnum.Yes.getType());
        this.save(newRole);
//        this.sysWorkFlowService.saveGroup(role.getRoleName());

        if(!StringUtils.isEmpty(role.getMenuId())){
            String[] menuIds = role.getMenuId().split(StringPool.COMMA);
            setRoleMenus(newRole, menuIds);
        }
    }

    @Override
    public void deleteRoles(String[] roleIds) throws Exception {
        //同步流程引擎
        for (String roleId : roleIds) {
            UpmpRole role = findById(roleId);
//            this.sysWorkFlowService.deleteGroup(role.getRoleName());
        }

        // 查找这些角色关联了那些用户
        List<String> userIds = this.upmpUserRoleService.findUserIdsByRoleId(roleIds);

        List<String> list = Arrays.asList(roleIds);

        this.upmpRoleMenuService.deleteRoleMenusByRoleId(roleIds);
        this.upmpUserRoleService.deleteUserRolesByRoleId(roleIds);

        baseMapper.deleteBatchIds(list);

        // 重新将这些用户的角色和权限缓存到 Redis中
        this.upmpUserManager.loadUserPermissionRoleRedisCache(userIds);
    }

    @Override
    public void updateRole(UpmpRoleVO role) throws Exception {
        // 查找这些角色关联了那些用户
        String[] roleId = {String.valueOf(role.getId())};
        List<String> userIds = this.upmpUserRoleService.findUserIdsByRoleId(roleId);

        UpmpUserInfoVO user = CommonUtils.getCurrentUser(upmpSysParamService);
        UpmpRole db = baseMapper.selectById(role.getId());
        BeanUtils.copyProperties(role, db);
        db.setLastUpdateTime(DateUtil.getDateFormat(new Date(), DateUtil.FULL_TIME_WITH_MILL_SPLIT_PATTERN));
        db.setLastOprId(user.getId());
        baseMapper.updateById(db);

        upmpRoleMenuMapper.delete(new LambdaQueryWrapper<UpmpRoleMenu>().eq(UpmpRoleMenu::getRoleId, role.getId()));

        String[] menuIds = role.getMenuId().split(StringPool.COMMA);
        setRoleMenus(db, menuIds);

        // 重新将这些用户的角色和权限缓存到 Redis中
        this.upmpUserManager.loadUserPermissionRoleRedisCache(userIds);
    }

    @Override
    public List<UpmpRole> getAllRoles(UpmpRoleVO role) {
        LambdaQueryWrapper<UpmpRole> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        if(!StringUtils.isEmpty(role.getInstId())){
            lambdaQueryWrapper.eq(UpmpRole::getInstId,role.getInstId());
        }

        UpmpSysParam defaultInst = upmpSysParamService.getById(UpmpConstant.DEAFULT_INST_PARAM_ID);
        //当前用户ID
        UpmpUserInfoVO currentUser = RedpUpmpUtil.getCurrentUser(defaultInst.getPrimaryValue());
        if(!currentUser.isAdmin()){
            // 隐藏超级管理员角色
            lambdaQueryWrapper.ne(UpmpRole::getId, 1);
        }
        List<UpmpRole> roles = this.getBaseMapper().selectList(lambdaQueryWrapper);
        return roles;
    }

    /**
     * 将所有的叶子菜单或按钮保存到角色菜单表
     * @param role
     * @param menuIds
     */
    private void setRoleMenus(UpmpRole role, String[] menuIds) {
        List<String> selectedMenuIds = Arrays.asList(menuIds);
        List<UpmpRoleMenu> roleMenus = new ArrayList<>();
        QueryWrapper<UpmpMenu> lqw = new QueryWrapper<>();
        lqw.eq("app_type", ChannelTypeEnum.UPMP.getType());
        List<UpmpMenu> allUpmpMenus = upmpMenuService.list(lqw);

        selectedMenuIds.forEach(menuId -> {
            AtomicBoolean isLeaf = new AtomicBoolean(true);
            allUpmpMenus.forEach(menu->{
                if(menu.getParentId().equals(menuId)){
                    isLeaf.set(false);
                }
            });
            if(isLeaf.get()){
                UpmpRoleMenu rm = new UpmpRoleMenu();
                rm.setMenuId(menuId);
                rm.setRoleId(role.getId());
                rm.setInstId(role.getInstId());
                rm.setCreateTime(role.getCreateTime());
                rm.setCrtOrgId(role.getCrtOrgId());
                rm.setOprId(role.getOprId());
                rm.setLastUpdateTime(role.getLastUpdateTime());
                rm.setLastOprId(role.getLastOprId());
                roleMenus.add(rm);
            }

        });

        if(roleMenus.size()>0){
            upmpRoleMenuService.saveBatch(roleMenus);
        }

    }

}
